package my1024.controller;

import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Observable;

import my1024.model.BoxModel;
import my1024.utils.EventData;
import my1024.utils.EventType;

public class LogicController extends Observable {
	private LogicBoard logicBoard = null;
	private boolean isGameStarted = false;
	private boolean isGameOver = false;
	private boolean hasSpace = true;

	private ArrayList<EventData> listDelete;
	private ArrayList<EventData> listChange;

	public LogicController() {
		logicBoard = new LogicBoard(this);
		listDelete = new ArrayList<EventData>();
		listChange = new ArrayList<EventData>();
	}

	public void startGame() {
		if (!isGameStarted) {
			logicBoard.initBoard();
			isGameStarted = true;
		}
	}

	public void updateGameStatus() {
		isGameOver = !hasSpace && listDelete.isEmpty();
	}

	public void runOutOfSpace() {
		hasSpace = false;
	}

	public void addRandomBox(BoxModel box) {
		EventData data = new EventData(EventType.ADD_BOX, box);
		setChanged();
		notifyObservers(data);
	}

	public void addDeleteBox(BoxModel deleteBox) {
		EventData data = new EventData(EventType.DELETE_BOX, deleteBox);
		System.out.println("Add deleted box: " + data.toString());
		listDelete.add(data);
	}

	public void addChangeBox(EventType eventType, BoxModel oldBox, BoxModel newBox) {
		EventData data = new EventData(eventType, oldBox, newBox);
		System.out.println("Add changed box: " + data.toString());
		listChange.add(data);
	}

	public void processResetRotate() {
		EventData data = new EventData(EventType.CTRL_RESET_ROTATE);
		setChanged();

		notifyObservers(data);
	}

	public void processLogic(int keyCode) {
		if (isGameOver) {
			System.out.println("GAME OVER!");
			return;
		}

		resetListEventData();

		switch (keyCode) {
		case KeyEvent.VK_LEFT:
			logicBoard.processMoveLeft();
			break;
		case KeyEvent.VK_RIGHT:
			logicBoard.processMoveRight();
			break;
		case KeyEvent.VK_UP:
			logicBoard.processMoveUp();
			break;
		case KeyEvent.VK_DOWN:
			logicBoard.processMoveDown();
			break;
		default:
			break;
		}

		// for debug game matrix
		logicBoard.dump();

		// check if there are no more object to be deleted or moved, so gameover
		updateGameStatus();

		if (!isGameOver) {
			correctEventDataPosition(keyCode);
			logicBoard.genRandomPos();
		}
	}

	private void resetListEventData() {
		listChange.clear();
		listDelete.clear();
	}

	private void correctEventDataPosition(int keyCode) {
		for (int i = 0; i < listChange.size(); ++i) {
			EventData data = listChange.get(i);
			data.correctPosition(keyCode);
			setChanged();
			notifyObservers(data);
		}

		for (int i = 0; i < listDelete.size(); ++i) {
			EventData data = listDelete.get(i);
			data.correctPosition(keyCode);
			setChanged();
			notifyObservers(data);
		}
	}
}
